package com.auth.manager.security.login;

import com.auth.manager.security.service.CustomUserDetailsService;
import com.auth.manager.security.service.UserAccount;
import com.auth.manager.utils.PasswordUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;

/**
 * @version 1.0.0
 * @Date: 2022/4/27 10:43
 * @Author ZhuYouBin
 * @Description 用户认证，自定义认证服务提供方
 */
@Component
public class LoginProvider implements AuthenticationProvider {
    // 自定义用户认证逻辑
    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    // 查询数据库,进行真正的用户认证
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        /**
         * 这个方法里面需要做什么逻辑呢？？？
         * 1、获取用户名称、密码
         * 2、根据用户名称, 询数据库, 判断用户是否合法
         * 3、用户名合法, 判断密码是否正确
         * 4、密码正确, 封装用户[权限、角色]信息 UsernamePasswordAuthenticationToken 对象
         */
        // 1、获取用户名称和密码
        String username = authentication.getPrincipal().toString();
        String password = authentication.getCredentials().toString();

        // 2、校验用户名称是否合法
        UserAccount account = (UserAccount) customUserDetailsService.loadUserByUsername(username);

        // 3、校验密码是否正确
        if (!PasswordUtil.matches(password, account.getPassword())) {
            throw new AuthenticationServiceException("用户名或密码不正确");
        }

        // 4、认证成功,封装 UsernamePasswordAuthenticationToken 返回对象
        return new UsernamePasswordAuthenticationToken(username, account.getPassword(), account.getAuthorities());
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }
}
